package com.cdks.wuxiu.common.component.handler;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.cdks.wuxiu.common.component.constant.ApiCodeEnum;
import com.cdks.wuxiu.common.exception.ApiException;
import com.cdks.wuxiu.common.model.api.ApiResult;

import java.sql.SQLException;
import java.sql.SQLSyntaxErrorException;
import java.util.List;

/**
 * 全局异常处理类
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 全局异常 统一JSON格式返回
     */
    @ExceptionHandler(Exception.class)
    public ApiResult<Object> exception(Exception e) {
        log.error("服务器异常", e);

        if (e instanceof HttpMediaTypeNotSupportedException)
        {
            return ApiResult.failed(ApiCodeEnum.PARAM_ERROR, e.getMessage());
        }

        if (e instanceof NullPointerException)
        {
            return ApiResult.failed(ApiCodeEnum.SERVICE_ERROR, "NullPointerException");
        }

        if (e instanceof SQLException)
        {
            return ApiResult.failed(ApiCodeEnum.SERVICE_ERROR, "SQLException");
        }

        if (e instanceof SQLSyntaxErrorException)
        {
            return ApiResult.failed(ApiCodeEnum.SERVICE_ERROR, "SQLSyntaxErrorException");
        }

        return ApiResult.failed(ApiCodeEnum.SERVICE_ERROR);
    }

    /**
     * Spring Validation 校验异常
     */
    @ExceptionHandler({BindException.class, MethodArgumentNotValidException.class})
    public ApiResult<Object> validationException(Exception e) {
        BindingResult bindingResult;
        if (e instanceof BindException) {
            bindingResult = ((BindException) e).getBindingResult();
        } else {
            bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
        }

        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        StringBuilder errorMsg = new StringBuilder();
        for (FieldError error : fieldErrors) {
            errorMsg.append(error.getField()).append(":").append(error.getDefaultMessage()).append(",");
        }

        errorMsg.deleteCharAt(errorMsg.length() - 1);
        ApiResult<Object> result = ApiResult.failed(ApiCodeEnum.PARAM_ERROR, errorMsg.toString());
        log.info("异常返回:" + JSONUtil.toJsonStr(result));

        return result;
    }

    /**
     * 自定义 API接口异常
     */
    @ExceptionHandler(ApiException.class)
    public ApiResult<Object> apiException(ApiException e) {
        ApiResult<Object> result = ApiResult.failed(e.getRetCode(), e.getRetHint(), e.getRetData());
        log.info("异常返回:" + JSONUtil.toJsonStr(result));

        return result;
    }
}
